// 立即执行函数

// IIFE  Immediately Invoked Function Expression
//       立即地       调用     (函数       表达式)


// 函数声明 !== 函数表达式
// function test1() {
//   console.log('Function declaration');
// }

// 函数表达式  把一个(匿名)函数(函数声明式)赋值给一个变量的形式
// var test2 = function() {
//   console.log('Function Expression');
// }

// (): 对于函数名后面的括号，叫执行符号
// test1();
// test2();


// 语法错误，执行符号只能跟在函数表达式后面
// function test() {
//   console.log('Function declaration');
// }();


// 当一个函数需要立即执行的时候，该函数必须是表达式形式

// 表达式：
// 1
// (1)
// +1
// !1
// ~1

// var a = 1
// var a = function () {
//   console.log('Function Expression');
// }();
// + function () {
//   console.log('Function Expression');
// }();
// - function () {
//   console.log('Function Expression');
// }();
// ! function () {
//   console.log('Function Expression');
// }();
// ~ function () {
//   console.log('Function Expression');
// }();


// W3C 推荐的立即执行函数的编写规范
// ;(function () {
//   console.log('Function Expression');
// }())

// 实践中  语义更清晰
// ;(function () {
//   console.log('Function Expression');
// })()



(function test (a, b, c, d) {
  // 1. 可以创建一个与外界没有任何关联的作用域，独立作用域
  // 2. 执行完成以后，自动销毁
  // 3. ES3 ES5 立场上是没有模块概念，一般使用立即执行函数来模拟模块化
      // 模块：封闭作用域、抛出接口、属性
  // 向外部抛出一系列属性或方法
  // 可以在 window 上保存属性或方法
  console.log(test); // test函数本身
  console.log(test.length);
  console.log(arguments.length);
  console.log('Hello')
})(1, 2, 3);

// 立即执行函数是一个独立的作用域，里面定义的函数，外边无法访问
// test(); // undefined

